package com.skyable.common.config;

import com.alibaba.fastjson.JSON;
import com.skyable.common.annotation.*;
import com.skyable.common.utils.SaApiUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author GaoYuan
 * @date 2019/11/5 9:42
 * @desc 动态代理，需要注意的是，这里用到的是JDK自带的动态代理，代理对象只能是接口，不能是类
 */
@Slf4j
public class ServiceProxy implements InvocationHandler {

	private String requestUrl;
	protected ServiceProxy(String requestUrl) {
		this.requestUrl = requestUrl;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		String result = "";
		SaRequestMapping declaredAnnotation = method.getDeclaredAnnotation(SaRequestMapping.class);
		if (declaredAnnotation != null) {
			StringBuilder mappingUrl = new StringBuilder(declaredAnnotation.value());
			HashMap<String, Object> headerMap = headerMap(proxy, method, args);
			HashMap<String, Object> bodyMap = bodyMap(proxy, method, args);
			HashMap<String, Object> paramMap = paramMap(proxy, method, args);
			String responseType = declaredAnnotation.responseType();
			if(SaApiUtil.HEADER_CONTENT_TYPE_X_ZC_OBJECT.equals(responseType)) {
				result = SaApiUtil.doPost(requestUrl + mappingUrl, headerMap, JSON.toJSONString(bodyMap.get("body")));
			} else {
				updateRequestUrl(mappingUrl,paramMap);
				byte[] payload = getPayLoad(proxy, method, args);
				log.info("mappingUrl:" + mappingUrl);
				result = SaApiUtil.doPost(requestUrl + mappingUrl, headerMap, payload);
			}
		}
		return result;
	}

	private HashMap<String, Object> headerMap(Object proxy, Method method, Object[] args) {
		// 获取方法上的参数
		Parameter[] parameters = method.getParameters();
		HashMap<String, Object> hashMap = new HashMap<>(parameters.length);
		//设置默认请求头信息
		hashMap.put(SaApiUtil.HEADER_CONTENT_TYPE, SaApiUtil.HEADER_CONTENT_TYPE_X_ZC_OBJECT);
		for (int i = 0; i < parameters.length; i++) {
			Parameter parameter = parameters[i];
			SaRequestHeader declaredAnnotation = parameter.getDeclaredAnnotation(SaRequestHeader.class);
			if (declaredAnnotation != null && args[i] != null) {
				// 参数名称
				String paramName = declaredAnnotation.value();
				Object paramValue = args[i];
				log.info(paramName + "," + paramValue);
				hashMap.put(paramName, paramValue);
			}
		}
		return hashMap;
	}

	private HashMap<String, Object> bodyMap(Object proxy, Method method, Object[] args) {
		// 获取方法上的参数
		Parameter[] parameters = method.getParameters();
		HashMap<String, Object> hashMap = new HashMap<>(parameters.length);
		for (int i = 0; i < parameters.length; i++) {
			Parameter parameter = parameters[i];
			SaRequestBody declaredAnnotation = parameter.getDeclaredAnnotation(SaRequestBody.class);
			if (declaredAnnotation != null) {
				// 参数名称
				Object paramValue = args[i];
				log.info("body:" + JSON.toJSONString(paramValue));
				hashMap.put("body", paramValue);
			}
		}
		return hashMap;
	}

	private HashMap<String, Object> paramMap(Object proxy, Method method, Object[] args) {
		// 获取方法上的参数
		Parameter[] parameters = method.getParameters();
		HashMap<String, Object> hashMap = new HashMap<>(parameters.length);
		for (int i = 0; i < parameters.length; i++) {
			Parameter parameter = parameters[i];
			SaRequestParam declaredAnnotation = parameter.getDeclaredAnnotation(SaRequestParam.class);
			if (declaredAnnotation != null) {
				// 参数名称
				Object paramValue = args[i];
				hashMap = (HashMap)paramValue;
			}
		}
		return hashMap;
	}

	private byte[] getPayLoad(Object proxy, Method method, Object[] args) {
		byte[] payload = null;
		// 获取方法上的参数
		Parameter[] parameters = method.getParameters();
		HashMap<String, Object> hashMap = new HashMap<>(parameters.length);
		for (int i = 0; i < parameters.length; i++) {
			Parameter parameter = parameters[i];
			SaRequestPayload declaredAnnotation = parameter.getDeclaredAnnotation(SaRequestPayload.class);
			if (declaredAnnotation != null) {
				// 参数名称
				payload = (byte[]) args[i];
			}
		}
		return payload;
	}

	private StringBuilder updateRequestUrl(StringBuilder mappingUrl, Map<String,Object> paramMap) {
		if(!paramMap.isEmpty()) {
			mappingUrl.append("?");
			//拼接Url参数
			Set<Map.Entry<String, Object>> entries = paramMap.entrySet();
			for(Map.Entry<String,Object> entry : entries) {
				mappingUrl.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
			}
			//去除最后的&符号
			mappingUrl.deleteCharAt(mappingUrl.lastIndexOf("&"));
		}
		return mappingUrl;
	}
}
